package erfgame.frontend.desktop.view.terrain.iso.handler;

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;

import erfgame.core.Rotation;
import erfgame.core.world.World;

import erfgame.frontend.desktop.view.terrain.iso.IsometricTerrainView;

public class PanningInteractionHandler 
	extends BaseInteractionHandler {
	
	private IsometricTerrainView view;
	private int previousX;
	private int previousY;
	private boolean isDragging;
	private MouseEvent mouseDownEvent;
	
	public PanningInteractionHandler( IsometricTerrainView view ) {
		this.view = view;
	}
	
	public KeyEvent[] handleKeyEvent(KeyEvent e) {
		KeyEvent[] result;
		if( e.getID() == KeyEvent.KEY_PRESSED ) {
			switch( e.getKeyCode() ) {
			case KeyEvent.VK_UP:
				result = null;
				move( 0, view.getCurrentWorld().getBlockHeight() );
				break;
			case KeyEvent.VK_DOWN:
				result = null;
				move( 0, -view.getCurrentWorld().getBlockHeight() );
				break;
			case KeyEvent.VK_LEFT:
				result = null;
				move( view.getCurrentWorld().getBlockWidth(), 0 );
				break;
			case KeyEvent.VK_RIGHT:
				result = null;
				move( -view.getCurrentWorld().getBlockWidth(), 0 );
				break;
			default:
				switch( e.getKeyChar() ) {
				case '>':
					view.adjustViewZ(1);
					result = null;
					view.repaint();
					break;
				case '<':
					result = null;
					view.adjustViewZ(-1);
					view.repaint();
					break;
				case ']':
					view.setCurrentRotation( Rotation.values()[ (view.getCurrentRotation().ordinal()+1)%Rotation.values().length ], null );
					result = null;
					break;
				case '[':
					int index = view.getCurrentRotation().ordinal();
					index--;
					Rotation[] rotations = Rotation.values();
					if( index < 0 ) {
						index = rotations.length + index;
					}
					view.setCurrentRotation( rotations[index], null);
					result = null;
					break;
				default:
					result = new KeyEvent[]{e};
				}
			}
		} else {
			result = new KeyEvent[]{e};
		}
		return result;
	}

	public MouseEvent[] handleMouseEvent(MouseEvent e) {
		MouseEvent[] result;
		switch( e.getID() ) {
		case MouseEvent.MOUSE_PRESSED:
			if( e.getButton() == MouseEvent.BUTTON3 ) {
				this.previousX = e.getX();
				this.previousY = e.getY();
				this.isDragging = true;
				this.mouseDownEvent = e;
				result = null;
			} else {
				result = new MouseEvent[]{e};
			}
			break;
		case MouseEvent.MOUSE_DRAGGED:
			if( isDragging ) {
				int dx = e.getX() - this.previousX;
				int dy = e.getY() - this.previousY;
				this.previousX = e.getX();
				this.previousY = e.getY();
				move( dx, dy );
				result = null;
				this.mouseDownEvent = null;
			} else {
				result = new MouseEvent[]{e};
			}
			break;
		case MouseEvent.MOUSE_RELEASED:
			if( e.getButton() == MouseEvent.BUTTON3 ) {
				isDragging = false;
				if( this.mouseDownEvent != null ) {
					result = new MouseEvent[]{ this.mouseDownEvent, e };
					this.mouseDownEvent = null;
				} else {
					result = null;					
				}
			} else {
				result = new MouseEvent[]{e};
			}
			break;
		default:
			 result = new MouseEvent[]{e};
			 break;
		}
		return result;
	}
	             
	public void move(int dx, int dy) {
		// move the viewport
		this.view.setWorldOffsets(
				this.view.getWorldX() - dx, 
				this.view.getWorldY() - dy*2
		);
		this.view.repaint();
	}

	@Override
	public MouseWheelEvent[] handleMouseWheelEvent(MouseWheelEvent e) {
		this.view.adjustViewZ( e.getWheelRotation() );
		this.view.repaint();
		return null;
	}
}
